package com.sq108.template.web.filter;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import tc.app.log.sqsyslog.ISqSysLogger;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.*;


@Component
public class MyLogInterceptor implements HandlerInterceptor {

    @Autowired
    private ISqSysLogger sqSysLogger;

    private Set<String> ignoreHeaders = new HashSet<>(Arrays.asList(
            ("connection,content-length,content-type,accept-encoding,accept-language,accept,host," +
                    "user-agent,postman-token,cache-control,origin").split(",")));


    @Override
    public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
        long startTime = System.currentTimeMillis();
        httpServletRequest.setAttribute("startTime", startTime);
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
        long startTime = (Long) httpServletRequest.getAttribute("startTime");
        long executeTime = System.currentTimeMillis() - startTime;
        httpServletRequest.setAttribute("duration", executeTime);
    }

    @Override
    public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
        Long duration = (Long) httpServletRequest.getAttribute("duration");

        // url
        String url = httpServletRequest.getServerName() + httpServletRequest.getRequestURI();
        // headers
        Map<String, String> headers = getHeadersInfo(httpServletRequest);
        // ip
//        String ip = httpServletRequest.getRemoteAddr();
        // 请求方式
//        String method = httpServletRequest.getMethod();

        //9.获取post和get两种请求参数
//        String params = getParams(httpServletRequest);

        StringBuilder sb = new StringBuilder();
        sb.append(httpServletRequest.getRequestURL());
        sb.append("?");
        sb.append(httpServletRequest.getQueryString());
        sb.append(":");
        sb.append(headers.toString());

        if (e == null) {
            sqSysLogger.apiUrl(sb.toString(), url, duration);
        } else {
            String message = sb.toString();
            String stackTrace = e.getMessage();
            sqSysLogger.apiUrlException(url, message, duration, stackTrace + getStackTrace(e.getStackTrace()));

        }
    }

    private String getParams(HttpServletRequest httpServletRequest) {
        Enumeration<String> names = httpServletRequest.getParameterNames();
        if (names != null) {
            Map<String, Object> map = new HashMap<>();
            while (names.hasMoreElements()) {
                String name = names.nextElement();
                String value = httpServletRequest.getParameter(name);
                map.put(name, value);
            }
            return map.toString();
        }
        return "";
    }

    private Map<String, String> getHeadersInfo(HttpServletRequest request) {
        Map<String, String> map = new HashMap<>();
        Enumeration headerNames = request.getHeaderNames();
        while (headerNames.hasMoreElements()) {
            String key = (String) headerNames.nextElement();
            if (!ignoreHeaders.contains(key.toLowerCase())){
                String value = request.getHeader(key);
                map.put(key, value);
            }
        }
        return map;
    }

    private String getStackTrace(StackTraceElement[] exceptionStack) {
        if (exceptionStack == null || exceptionStack.length == 0) {
            return "";
        }
        StringBuilder message = new StringBuilder();
        for (StackTraceElement ste : exceptionStack) {
            message.append("\n\tat ").append(ste);
        }
        return message.toString();
    }
}
